package chat

/**
date:2017/1/9
author:tangkaijun
*/

import (
	"log"
)

type Hub struct { //维护每一个客户端，并作为信息分发器使用，为每个客户端分发信息
	Clients    map[*Client]bool //保存注册过的客户端
	Register   chan *Client     //当前注册的客户端
	UnRegister chan *Client     //当前注销的客户端
	BroadCast  chan []byte      //从客户端接收的信息并广播到每一个客户端
}

/**创建一个客户端信息分发器*/
func NewHub() *Hub {
	return &Hub{
		Clients:    make(map[*Client]bool),
		Register:   make(chan *Client),
		UnRegister: make(chan *Client),
		BroadCast:  make(chan []byte),
	}
}

/**启动运行Hub*/
func (this *Hub) BeginRun() {
	for {
		select {
		case client := <-this.Register: //此处会阻塞，直到读取到有客户端注册，则执行
			this.Clients[client] = true
			//向各个客户端发送广播信息，通知当前用户已经登录
			select {
			case message := <-this.BroadCast:
				for c := range this.Clients {
					select {
					case c.SendMessage <- message:
					default:
						close(c.SendMessage) //关闭客户端发送信息的通道
						delete(this.Clients, c)
					}
				}
			}
		case client := <-this.UnRegister: //处理未注册的客户端应用
			if _, ok := this.Clients[client]; ok {
				log.Println("用户", client.Username, "注销")
				//向客户端发送广播注销信息
				select {
				case message := <-this.BroadCast:
					for c := range this.Clients {
						select {
						case c.SendMessage <- message:
						default:
							close(c.SendMessage) //关闭客户端发送信息的通道
							delete(this.Clients, c)
						}
					}
				}
				close(client.SendMessage)    //关闭当前注销客户端发送信息的通道
				delete(this.Clients, client) //将当前注销的客户端删除
			}
		case message := <-this.BroadCast: //读取客户端发送过来的信息
			for client := range this.Clients { //遍历每一个客户端广播信息
				select {
				case client.SendMessage <- message:
				default:
					close(client.SendMessage) //关闭客户端发送信息的通道
					delete(this.Clients, client)
				}
			}
		}
	}
}
